package main

import (
	"fmt"
	"math/rand"
	"time"
)

//Test the concurrency features of Go
//Concurrency is the composition of independently executing computations.
//Concurrency is not parallelism, although it enables parallelism.
//Reference https://www.youtube.com/watch?v=f6kdp27TYZs

func main() {
	c := make(chan string) //Channel
	//Channels are first-class values,like strings
	//Channel allows communicating between two goroutines and also synchronizing
	//Buffered channels remove synchronization
	//var c chan int
	//c := make(chan int)
	//c <- 1      //send to channel, wait for receiver to be ready
	//value = <- c //receive from channel, wait for a value to be sent

	go boring("boring!", c) //launch a goroutine
	//goroutine is an independently executing function, not a thread

	fmt.Println("I'm listening...")
	for i := 0; i < 5; i++ {
		fmt.Printf("You say: %q\n", <-c)
	}

	gc := genBoring("gen boring!")
	for i := 0; i < 5; i++ {
		fmt.Printf("He says: %q\n", <-gc)
	}
	fmt.Println("You're both boring. I'm leaving.")
}

func boring(msg string, c chan string) {
	for i := 0; ; i++ {
		c <- fmt.Sprintf("%s %d", msg, i)
		//fmt.Println(msg,i)
		//time.Sleep(time.Second)
		time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
	}
}

//generator
func genBoring(msg string) <-chan string {
	c := make(chan string)
	go func() {
		for i := 0; ; i++ {
			c <- fmt.Sprintf("%s %d", msg, i) //wait for receiver to be ready
			//fmt.Println(msg,i)
			//time.Sleep(time.Second)
			time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
		}
	}()
	return c //return the channel
}
